home *** CD-ROM | disk | FTP | other *** search
- {************************************************}
- { }
- { Turbo Vision File Manager Demo }
- { Copyright (c) 1992 by Borland International }
- { }
- {************************************************}
-
- unit Tools;
-
- {$X+,V-}
-
- interface
-
- uses Drivers, Objects, Views, Dialogs, Memory, App, MsgBox,
- Globals, FileCopy, Gauges, Dos;
-
- type
- String2 = String[2];
- String4 = String[4];
- TConfigHeader = String[24];
-
- { Used to display status messages }
- PStatusBox = ^TStatusBox;
- TStatusBox = object(TDialog)
- procedure HandleEvent(var Event: TEvent); virtual;
- end;
-
- { buffered file copy object }
- PCopier = ^TCopier;
- TCopier = object(TFileCopy)
- procedure ReadMsg(const FName: FNameStr; Progress: Longint); virtual;
- procedure WriteMsg(const FName: FNameStr; Progress: Longint); virtual;
- function IOError(const FName: FNameStr; ECode:Integer) : erAction; virtual;
- end;
-
- { generate a cmOK if double clicked }
- POkListBox = ^TOkListBox;
- TOkListBox = object(TListBox)
- procedure SelectItem(Item: Integer); virtual;
- end;
-
- { ShowStatusBox displays a status dialog, using StatusMsg as the string }
- { to display. The status box responds to the cmStatusUpdate command by }
- { redrawing the text. }
- procedure ShowStatusBox;
-
- { KillStatusBox removes the status box from the screen }
- procedure KillStatusBox;
-
- { Return True if the passed list contains any tagged files }
- function HasTaggedFiles(P: PFileList) : Boolean;
-
- { Return the path and filename (no extension) of the exe }
- function GetExeBaseName: String;
-
- { Convert strings to upper and lower case }
- procedure UpperCase(var s: String);
- procedure LowerCase(var s: String);
-
- { Return a right justified number (in an 8 character field) }
- function RJustNum(L: Longint): String;
-
- { Pad right end of string to Len bytes }
- function Pad(s: String; Len: Byte): String;
-
- { Return a fully trimmed copy of Original }
- function FullTrim(const Original: String): String;
-
- { Return string value of W, optionally with leading zero if Pad=True }
- function TwoDigit(W: Word; Pad: Boolean): String2;
-
- { Return 4 digit string representation of W }
- function FourDigit(W: Word): String4;
-
- { Return a string version of the Date/Time longint. Opts=$01 adds the }
- { date portion. Opts=$02 adds time, Opts=$03 adds both }
- function FormatDateTime(DT: Longint; Opts: Word): String;
-
- { Return the 4 character string representation of the attribute word }
- function FormatAttr(Attr: Word): String4;
-
- { Return True if file is a .BAT, .COM, or .EXE }
- function IsExecutable(const FileName: FNameStr): Boolean;
-
- { Execute the passed file, asks for parameters }
- procedure ExecuteFile(FileName: FNameStr);
-
- { View passed file as Hex, Text, or with Custom Viewer }
- procedure ViewAsHex(const FileName: FNameStr);
- procedure ViewAsText(const FileName: FNameStr);
- procedure ViewCustom(const FileName: FNameStr);
-
- { Return True if the passed drive letter is valid }
- function DriveValid(Drive: Char): Boolean;
-
- { Return a selected drive letter from listbox of valid drives }
- function SelectDrive: Char;
-
- { Invalidate the passed directory by issuing a cmInvalidDir broadcast }
- procedure InvalidateDir(Path: FNameStr);
-
- { Copy either tagged or current file to a destination path }
- procedure HandleFileCopy(const Path: FNameStr; P: PFileList; Current: Integer);
-
- { Delete file if user confirms the deletion, return error code }
- function SafeDelete(FileName: FNameStr): Integer;
-
- { Handle deleting one or multiple files from a file list }
- procedure HandleFileDelete(const Path: FNameStr; List: PFileList;
- Current: Integer);
-
- { Present the Rename file dialog }
- procedure RenameFile(const Path: FNameStr; F: PFileRec);
-
- { Present the Change Attribute dialog }
- procedure ChangeAttr(const Path: FNameStr; F:PFileRec);
-
- { Allow user to specify what viewer program to use }
- procedure InstallViewer;
-
- { Allow user to specify the display options }
- procedure SetDisplayPrefs;
-
- { Save and load the configuration file }
- procedure SaveConfig;
- procedure ReadConfig;
-
- { Execute the passed string literally }
- procedure RunDosCommand(Command: String);
-
- { Return a TFileNameRec built from the passed filespec. This structure }
- { allows for easier comparisons by other procedures }
- function NewFileNameRec(const Path: FNameStr): PFileNameRec;
-
- { Perform a drag & drop copy }
- procedure DragDropCopy(Mover: PFileMover; Dest: PathStr);
-
- { return true if this name matches the wildcard }
- function WildCardMatch(const Name, Card: FNameStr): Boolean;
-
- const
- StatusMsg : String = '';
-
- implementation
-
- uses ViewHex, ViewText, Strings, Equ, Assoc;
-
- const
- StatusBox : PStatusBox = nil;
- StatusPMsg : PString = @StatusMsg;
-
- ConfigHeader : TConfigHeader = 'TVFM Configuration File'#26;
-
- { General utility procedures }
-
- procedure ShowStatusBox;
- var
- R: TRect;
- P: PView;
- begin
- if StatusBox <> nil then exit;
- R.Assign(0,0,40,5);
- StatusBox := New(PStatusBox, Init(R, 'Status'));
- with StatusBox^ do
- begin
- Options := Options or ofCentered;
- Options := Options and (not ofBuffered);
- Flags := Flags and (not wfClose) and (not wfMove);
- R.Assign(2,2,38,3);
- P := New(PParamText, Init(R, ^C'%s', 1));
- Insert(P);
- end;
- StatusMsg := '';
- StatusPMsg := @StatusMsg;
- StatusBox^.SetData(StatusPMsg);
- Desktop^.Insert(StatusBox);
- end;
-
- procedure ShowCopyStatusBox(MaxSize: Longint);
- var
- R: TRect;
- P: PView;
- begin
- if StatusBox <> nil then exit;
- R.Assign(0,0,40,7);
- StatusBox := New(PStatusBox, Init(R, 'Status'));
- with StatusBox^ do
- begin
- Options := Options or ofCentered;
- Options := Options and (not ofBuffered);
- Flags := Flags and (not wfClose) and (not wfMove);
- R.Assign(2,2,38,3);
- P := New(PParamText, Init(R, ^C'%s', 1));
- Insert(P);
- R.Assign(5,4,34,5);
- Insert(New(PBarGauge, Init(R, MaxSize)));
- R.Assign(2,4,4,5);
- Insert(New(PStaticText, Init(R, '0%')));
- R.Assign(35,4,39,5);
- Insert(New(PStaticText, Init(R, '100%')));
- end;
- StatusMsg := '';
- StatusPMsg := @StatusMsg;
- StatusBox^.SetData(StatusPMsg);
- Desktop^.Insert(StatusBox);
- end;
-
- procedure KillStatusBox;
- begin
- if StatusBox <> nil then
- begin
- Dispose(StatusBox, Done);
- StatusBox := nil;
- end;
- end;
-
- { Return TRUE if the passed list has tagged files in it }
- function HasTaggedFiles(P: PFileList) : Boolean;
- var
- Has: Boolean;
- i: Integer;
- begin
- Has := False;
- i := 0;
- while (i < P^.Count) and (not Has) do
- begin
- Has := PFileRec(P^.At(i))^.Tagged;
- Inc(i);
- end;
- HasTaggedFiles := Has;
- end;
-
- function GetExeBaseName : String;
- var
- ExeFileName: FNameStr;
- D: DirStr;
- N: NameStr;
- E: ExtStr;
- begin
- ExeFileName := ParamStr(0);
- if ExeFileName = '' then
- ExeFileName := FSearch(EXEName, GetEnv('PATH'));
- ExeFileName := FExpand(ExeFileName);
- FSplit(ExeFileName, D, N, E);
- GetExeBaseName := D + N;
- end;
-
- procedure UpperCase(var s:string);
- var
- i : Integer;
- begin
- for i := 1 to Length(s) do
- s[i] := Upcase(s[i]);
- end;
-
- procedure LowerCase(var s:string);
- var
- i : Integer;
- begin
- for i := 1 to Length(s) do
- if s[i] in ['A'..'Z'] then Inc(s[i], 32);
- end;
-
- function RJustNum(L: Longint): String;
- var
- s: String;
- begin
- FormatStr(s, '%8d', L);
- RJustNum := s;
- end;
-
- function Pad(s: String; Len: Byte): String;
- begin
- if Length(s) < Len then
- FillChar(s[Succ(Length(s))], Len-Length(s), ' ');
- s[0] := Char(Len);
- Pad := s;
- end;
-
- function FullTrim(const Original: String): String;
- var
- S: String;
- begin
- S := Original;
- while (S[0] > #0) and (S[Length(S)] = #32) do Dec(S[0]); { trim left }
- while (S[0] > #0) and (S[1] = #32) do
- begin
- Move(S[2], S[1], Pred(Length(S)));
- Dec(S[0]);
- end;
- FullTrim := S;
- end;
-
- function TwoDigit(W: Word; Pad: Boolean) : String2;
- var
- s: String2;
- begin
- Str(W:2, s);
- if Pad and (s[1] = ' ') then s[1] := '0';
- TwoDigit := s;
- end;
-
- function FourDigit(W: Word) : String4;
- var
- s: String4;
- begin
- Str(W:4, s);
- FourDigit := s;
- end;
-
- function FormatDateTime(DT: Longint; Opts: Word): String;
- var
- s: String;
- t: DateTime;
- begin
- UnpackTime(DT, t);
- s := '';
- if (Opts and 1) <> 0 then { add the date }
- begin
- s := s + TwoDigit(t.Month, False) + '-' + TwoDigit(t.Day, True);
- s := s + '-' + Copy(FourDigit(t.Year),3,2);
- end;
- if (Opts and 2) <> 0 then { add the time }
- begin
- if s <> '' then s := s + ' ';
- s := s + TwoDigit(t.Hour, True) + ':' + TwoDigit(t.Min, True) + ':' +
- TwoDigit(t.Sec, True);
- end;
- FormatDateTime := s;
- end;
-
- function FormatAttr(Attr: Word): String4;
- var
- s: String4;
- begin
- s := 'ยทยทยทยท';
- if Attr and Archive = Archive then s[1] := 'A';
- if Attr and ReadOnly = ReadOnly then s[2] := 'R';
- if Attr and SysFile = SysFile then s[3] := 'S';
- if Attr and Hidden = Hidden then s[4] := 'H';
- FormatAttr := s;
- end;
-
- function IsExecutable(const FileName: FNameStr): Boolean;
- var
- D: DirStr;
- N: NameStr;
- E: ExtStr;
- begin
- FSplit(FExpand(FileName), D, N, E);
- IsExecutable := (E = '.EXE') or (E = '.COM') or (E = '.BAT');
- end;
-
- procedure ExecuteFile(FileName: FNameStr);
- var
- D: PDialog;
- R: TRect;
- P: PView;
- Dir: DirStr;
- Name: FNameStr;
- E: ExtStr;
- Event: TEvent;
- Params: string[80];
- Command: string[80];
- L: array[0..2] of Longint;
- ParamPos: Integer;
- Association: PAssociation;
- begin
- FSplit(FExpand(FileName), Dir, Name, E);
- Name := Name + E;
- Association := nil;
-
- Command := '';
- Params := '';
- { Does an association exist for this file? }
- if not IsExecutable(FileName) then
- begin
- Association := GetAssociatedCommand(E);
- if Association <> nil then Command := Association^.Cmd^;
- if Command = '' then
- begin
- L[0] := Longint(@FileName);
- MessageBox(RezStrings^.Get(sNoAssociation), @L, mfError +
- mfOKButton);
- Exit;
- end
- else
- begin
- ParamPos := Pos(' ', Command);
- if ParamPos > 0 then
- begin
- Params := Copy(Command, ParamPos + 1, $FF);
- Delete(Command, ParamPos, $FF);
- Params := Params + ' ' + FileName;
- end
- else
- Params := FileName;
- end;
- end
- else
- begin
- Command := FileName;
- Params := '';
- end;
-
- R.Assign(0,0,50,8);
- D:= New(PDialog, Init(R, 'Execute Program'));
- with D^ do
- begin
- Options := Options or ofCentered;
- R.Assign(2,2,15,3);
- Insert(New(PStaticText, Init(R, ' Executing:')));
- R.Assign(15,2,48,3);
- Insert(New(PStaticText, Init(R, Command)));
-
- R.Assign(15,3,48,4);
- P := New(PInputLine, Init(R, 80));
- Insert(P);
- R.Assign(2,3,15,4);
- Insert(New(PLabel, Init(R, '~P~arameters', P)));
-
- R.Assign(12,5,24,7);
- Insert(New(PButton, Init(R, '~O~K', cmOK, bfDefault)));
- R.Move(14,0);
- Insert(New(PButton, Init(R, '~C~ancel', cmCancel, bfNormal)));
- SelectNext(False);
- end;
-
- if ( (Association <> nil) and (not Association^.Prompt)) or
- (Application^.ExecuteDialog(D, @Params) = cmOK) then
- begin
- DoneSysError;
- DoneEvents;
- DoneVideo;
- DoneDosMem;
- SwapVectors;
-
- if E = '.BAT' then
- begin
- Command := GetEnv('COMSPEC');
- Params := '/c ' + FileName + Params;
- end;
-
- Exec(Command, Params);
- SwapVectors;
-
- PrintStr(RezStrings^.Get(sPressAnyKey));
- Event.What := evNothing;
- repeat
- GetKeyEvent(Event);
- until Event.What <> evNothing;
-
- InitDosMem;
- InitVideo;
- InitEvents;
- InitSysError;
- Application^.Redraw;
-
- if DosError <> 0 then
- begin
- L[0] := DosError;
- L[1] := Longint(@Command);
- MessageBox(RezStrings^.Get(sExecErr), @L, mfError + mfOKButton);
- end else
- begin
- L[0] := DosExitCode and $FF;
- if L[0] <> 0 then
- MessageBox(RezStrings^.Get(sExecRetCode), @L,
- mfInformation + mfOKButton);
- end;
- end;
- end;
-
- { view file procedures }
- procedure ViewAsHex(const FileName: FNameStr);
- var
- H: PHexWindow;
- R: TRect;
- begin
- R.Assign(0,0,72,15);
- H := New(PHexWindow, Init(R, FileName));
- H^.Options := H^.Options or ofCentered;
- Desktop^.Insert(H);
- end;
-
- procedure ViewAsText(const FileName: FNameStr);
- var
- T: PTextWindow;
- R: TRect;
- begin
- R.Assign(0,0,72,15);
- T := New(PTextWindow, Init(R, FileName));
- T^.Options := T^.Options or ofCentered;
- Desktop^.Insert(T);
- end;
-
- procedure ViewCustom(const FileName: FNameStr);
- var
- Params : FNameStr;
- Command : FNameStr;
- D: DirStr;
- N: NameStr;
- E: ExtStr;
- L : array[0..1] of Longint;
- Msg: String;
- PS: PString;
- begin
- { create the program name }
-
- if FullTrim(Viewer) = '' then
- begin
- MessageBox(RezStrings^.Get(sNoViewerErr), nil, mfError + mfOKButton);
- Exit;
- end;
-
- FSplit(Viewer, D, N, E);
-
- DoneSysError;
- DoneEvents;
- DoneVideo;
- DoneDosMem;
- SwapVectors;
-
- if E = '.BAT' then
- begin
- Command := GetEnv('COMSPEC');
- Params := '/c ' + Viewer + ' ' + FileName;
- end
- else
- begin
- Command := Viewer;
- Params := FileName;
- end;
-
- Exec(Command, Params);
- SwapVectors;
-
- InitDosMem;
- InitVideo;
- InitEvents;
- InitSysError;
- Application^.Redraw;
-
- if DosError <> 0 then
- begin
- L[0] := DosError;
- L[1] := Longint( @Viewer );
- MessageBox(RezStrings^.Get(sInvokeErr), @L, mfError + mfOKButton);
- end;
-
- end;
-
-
- function DriveValid(Drive: Char): Boolean; assembler;
- asm
- MOV AH,19H { Save the current drive in BL }
- INT 21H
- MOV BL,AL
- MOV DL,Drive { Select the given drive }
- SUB DL,'A'
- MOV AH,0EH
- INT 21H
- MOV AH,19H { Retrieve what DOS thinks is current }
- INT 21H
- MOV CX,0 { Assume false }
- CMP AL,DL { Is the current drive the given drive? }
- JNE @@1
- MOV CX,1 { It is, so the drive is valid }
- MOV DL,BL { Restore the old drive }
- MOV AH,0EH
- INT 21H
- @@1: XCHG AX,CX { Put the return value into AX }
- end;
-
- { Return a redirected device entry into the specified buffers }
- function GetRedirEntry(Entry: Word; Local, Net: Pointer): Boolean; assembler;
- asm
- PUSH DS
- LDS SI,Local
- LES DI,Net
- MOV AX,5F02h
- MOV BX,Entry
- INT 21h
- POP DS
- SBB AL,AL
- INC AL
- end;
-
- { return a list of redirected devices (drives only) }
- function RedirDeviceList: PDeviceCollection;
- var
- List: PDeviceCollection;
- Device: PDeviceRec;
- P: PChar;
- I: Word;
- LocalName: array[0..15] of char;
- NetworkName: array[0..127] of char;
- begin
- List := nil;
-
- {$IFNDEF DPMI}
- List := New(PDeviceCollection, Init(10,10));
- for I := 0 to 99 do
- begin
- if GetRedirEntry(I, @LocalName, @NetworkName) then
- begin
- if (LocalName[0] in ['D'..'Z']) and (LocalName[1] = ':') then
- begin
- New(Device);
- Device^.LocalName := LocalName[0];
- P := @NetworkName[2];
- Device^.NetworkName := NewStr( StrPas(P) );
- List^.Insert(Device);
- end;
- end
- else Break;
- end;
-
- if List^.Count = 0 then
- begin
- Dispose(List, Done);
- List := nil;
- end;
- {$ENDIF}
-
- RedirDeviceList := List;
- end;
-
-
- function ValidDriveList: PStringCollection;
- var
- DriveList: PStringCollection;
- DeviceList: PDeviceCollection;
- Drive: Char;
- Device: PDeviceRec;
- S: String;
-
- function DriveMatch(P: PDeviceRec): Boolean; far;
- begin
- DriveMatch := Drive = P^.LocalName;
- end;
-
- begin
- DriveList := New(PStringCollection, Init(26,0));
- DeviceList := RedirDeviceList;
- for Drive := 'A' to 'Z' do
- begin
- if DriveValid(Drive) then
- begin
- S := Drive + ':';
- if DeviceList <> nil then
- begin
- Device := DeviceList^.FirstThat(@DriveMatch);
- if Device <> nil then S := S + ' ' + Device^.NetworkName^;
- end;
- DriveList^.Insert(NewStr(S));
- end;
- end;
- if DriveList^.Count = 0 then
- begin
- Dispose(DriveList, Done);
- DriveList := nil;
- end;
- ValidDriveList := DriveList;
- if DeviceList <> nil then Dispose(DeviceList, Done);
- end;
-
- function SelectDrive : Char;
- var
- R: TRect;
- D: PDialog;
- LB: PListBox;
- SB: PScrollBar;
- P: PString;
- DriveList: PStringCollection;
- CurDir: String;
-
- function IsCurrentDirectory(Dir: PString): Boolean; far;
- begin
- IsCurrentDirectory := Dir^[1] = CurDir[1];
- end;
-
- begin
- GetDir(0, CurDir); { save this value }
- SelectDrive := ' ';
- DriveList := ValidDriveList;
-
- if DriveList = nil then
- begin
- MessageBox(RezStrings^.Get(sNoDrivesErr), nil, mfError + mfOKButton);
- Exit;
- end;
-
- R.Assign(0, 0, 53, 13);
- D := New(PDialog, Init(R, 'Select Drive'));
- with D^ do
- begin
- Options := Options or ofCentered;
- R.Assign(50, 3, 51, 9);
- SB := New(PScrollBar, Init(R));
- Insert(SB);
- R.Assign(2, 3, 50, 9);
- LB := New(POkListBox, Init(R, 1, SB));
- Insert(LB);
- LB^.NewList(DriveList);
- R.Assign(2, 2, 19, 3);
- Insert(New(PLabel, Init(R, '~D~rives', LB)));
- R.Assign(12, 10, 24, 12);
- Insert(New(PButton, Init(R, '~O~K', cmOK, bfDefault)));
- R.Move(16, 0);
- Insert(New(PButton, Init(R, '~C~ancel', cmCancel, bfNormal)));
- SelectNext(False);
- end;
-
- P := DriveList^.FirstThat(@IsCurrentDirectory);
- if P <> nil then
- LB^.FocusItem(DriveList^.IndexOf(P));
-
- if Desktop^.ExecView(D) = cmOK then
- begin
- P := DriveList^.At(LB^.Focused);
- if P <> nil then SelectDrive := P^[1];
- end;
- Dispose(DriveList, Done);
- Dispose(D, Done);
- end;
-
- procedure InvalidateDir(Path: FNameStr);
- begin
- Message(Desktop, evBroadcast, cmInvalidDir, @Path);
- end;
-
- procedure HandleFileCopy(const Path: FNameStr; P: PFileList; Current: Integer);
- var
- Dest, S, D: string[80];
- C: TCopier;
- Dlg: PDialog;
- TotalSize: Longint;
-
- procedure CopyTagged(F: PFileRec); far;
- begin
- if F^.Tagged then
- begin
- S := Path + '\' + F^.Name + F^.Ext;
- D := Dest + F^.Name + F^.Ext;
- C.CopyFile(S, D, coNormal);
- end;
- end;
-
- procedure AddSizes(F: PFileRec); far;
- begin
- if F^.Tagged then Inc(TotalSize, F^.Size);
- end;
-
- procedure CopySingle(F: PFileRec);
- begin
- S := Path + '\' + F^.Name + F^.Ext;
- D := Dest + F^.Name + F^.Ext;
- C.CopyFile(S, D, coNormal);
- end;
-
- begin
- Dest := '';
- Dlg := PDialog( RezFile.Get('CopyDialog') );
- Application^.ExecuteDialog(Dlg, @Dest);
- if Dest = '' then Exit;
-
- Dest := FExpand(Dest);
- if (Dest[Length(Dest)] <> '\') and (Dest[Length(Dest)] <> ':') then
- Dest := Dest + '\';
-
- C.Init(20);
-
- TotalSize := 0;
- if HasTaggedFiles(P) then P^.ForEach(@AddSizes)
- else TotalSize := PFileRec(P^.At(Current))^.Size;
- ShowCopyStatusBox(TotalSize);
-
- if HasTaggedFiles(P) then P^.ForEach(@CopyTagged)
- else CopySingle( PFileRec( P^.At(Current) ) );
-
- C.Done;
- KillStatusBox;
-
- if Dest[Length(Dest)] = '\' then Dec(Dest[0]);
- InvalidateDir(Dest);
- end;
-
- function SafeDelete(FileName: FNameStr): Integer;
- var
- R: Word;
- F: File;
- C: Word;
- L: Longint;
- D: PDialog;
- Params: array[0..1] of Pointer;
- Name : FNameStr;
- Msg : String;
- Attr: Word;
- begin
- SafeDelete := -1;
- C := cmYes; { default value }
- Assign(F, FileName);
- GetFAttr(F, Attr);
- if DosError <> 0 then
- begin
- Params[0] := Pointer(L);
- Params[1] := @FileName;
- MessageBox(RezStrings^.Get(sAccessErr), @Params, mfError + mfOKButton);
- SafeDelete := L;
- Exit;
- end;
-
- if (Attr and ReadOnly) <> 0 then Msg := RezStrings^.Get(sFileIsReadOnly)
- else Msg := '';
- Params[0] := @FileName;
- Params[1] := @Msg;
-
- if ConfirmDelete then
- begin
- D := PDialog( RezFile.Get('ConfirmDelete') );
- C := Application^.ExecuteDialog(D, @Params);
- end;
-
- if C = cmYes then
- begin
- { if file was read-only, clear that attribute }
- if (Attr and ReadOnly) <> 0 then
- begin
- SetFAttr(F, Attr and (not ReadOnly));
- if DosError <> 0 then
- begin
- L := DosError;
- Params[0] := @Msg;
- Params[1] := Pointer(L);
- MessageBox(RezStrings^.Get(sSetAttrErr), @Params, mfError+mfOKButton);
- SafeDelete := DosError;
- Exit;
- end;
- end;
-
- { delete the file }
- {$I-}
- Erase(F);
- {$I+}
- L := IOResult;
- if L <> 0 then
- begin
- Params[0] := @Msg;
- Params[1] := Pointer(L);
- MessageBox(RezStrings^.Get(sDeleteErr), @Params, mfError+mfOKButton);
- SafeDelete := L;
- Exit;
- end
- else
- SafeDelete := 0;
- end;
- end;
-
- function RemoveDeadFiles(P: PFileList): Integer;
- var
- F : PFileRec;
- i : Integer;
- Count: Integer;
- begin
- Count := 0;
- i := 0;
- while i < P^.Count do
- begin
- F := P^.At(i);
- if F^.Name[1] = #0 then
- begin
- if F^.Tagged then
- begin
- F^.Toggle;
- Message(Desktop, evBroadcast, cmTagChanged, F);
- end;
- Inc(Count);
- P^.AtFree(i);
- end
- else inc(i);
- end;
- RemoveDeadFiles := Count;
- end;
-
- function DeleteMultFiles(Path: FNameStr; List: PFileList): Boolean;
- var
- F: PFileRec;
- N: FNameStr;
-
- procedure DeleteIfTagged(F: PFileRec); far;
- begin
- if F^.Tagged then
- begin
- N := Path + '\' + F^.Name + F^.Ext;
- StatusMsg := RezStrings^.Get(sDeleting) + N;
- Message(StatusBox, evBroadcast, cmStatusUpdate, nil);
- if SafeDelete(N) = 0 then F^.Name[1] := #0; { mark as deleted }
- end;
- end;
-
- begin
- ConfirmDelete := False;
-
- StatusMsg := '';
- ShowStatusBox;
- List^.ForEach(@DeleteIfTagged);
- KillStatusBox;
-
- DeleteMultFiles := RemoveDeadFiles(List) > 0;
-
- ConfirmDelete := True;
- end;
-
- procedure HandleFileDelete(const Path: FNameStr; List: PFileList;
- Current: Integer);
- var
- D: PDialog;
- Command: Word;
- F: PFileRec;
- begin
-
- F := List^.At(Current);
- Command := cmNo; { default to only deleting current file }
-
- if HasTaggedFiles(List) then
- begin
- D := PDialog( RezFile.Get('DeleteWhich') );
- Command := Application^.ExecuteDialog(D, nil);
- end;
-
- if Command = cmNo then { only delete the current file }
- begin
- F := List^.At(Current);
- if SafeDelete(Path + '\' + F^.Name + F^.Ext) = 0 then
- InvalidateDir(Path);
- end
- else if Command = cmYes then { delete all marked files }
- begin
- if DeleteMultFiles(Path, List) then
- InvalidateDir(Path);
- end;
-
- end;
-
- procedure RenameFile(const Path: FNameStr; F: PFileRec);
- var
- D: PRenameDialog;
- Dir: DirStr;
- N: NameStr;
- E: ExtStr;
- begin
- D := New(PRenameDialog, Init(Path + '\' + F^.Name + F^.Ext));
- if D <> nil then
- begin
- if Application^.ExecuteDialog(D, nil) = cmOK then
- begin
- FSplit(D^.NewName, Dir, N, E);
- F^.Name := N;
- F^.Ext := E;
- InvalidateDir(Path);
- end;
- end;
- end;
-
- procedure ChangeAttr(const Path: FNameStr; F: PFileRec);
- var
- D: PAttrDialog;
- begin
- D := New(PAttrDialog, Init(Path + '\' + F^.Name + F^.Ext));
- if D <> nil then
- begin
- if Application^.ExecuteDialog(D, nil) = cmOK then
- begin
- F^.Attr := D^.NewAttr;
- InvalidateDir(Path);
- end;
- end
- else
- MessageBox(RezStrings^.Get(sReadAttrErr), nil,
- mfError + mfOKButton);
- end;
-
- procedure InstallViewer;
- var
- VPath: FNameStr;
- Valid, Done: Boolean;
- L: Longint;
- begin
- VPath := Viewer;
- Valid := False;
- Done := False;
- while (not Valid) and (not Done) do
- begin
- if InputBox(RezStrings^.Get(sCustomViewer), RezStrings^.Get(sPathAndName),
- VPath, SizeOf(FNameStr) - 1) = cmOK then
- begin
- UpperCase(VPath);
- VPath := FSearch(VPath, GetEnv('PATH'));
- if VPath = '' then
- begin
- MessageBox(RezStrings^.Get(sCantLocateOnPath), nil,
- mfError + mfOKButton);
- end
- else if not IsExecutable(VPath) then
- begin
- L := Longint(@VPath);
- MessageBox(RezStrings^.Get(sFileNotAnExe), @L, mfError+mfOKButton);
- end
- else Valid := True;
- end
- else Done := True;
- end;
- if Valid then Viewer := VPath;
- end;
-
- procedure SetDisplayPrefs;
- var
- D: PDialog;
- SaveMask: string[12];
- begin
- D := PDialog( RezFile.Get('DisplayPref') );
-
- SaveMask := ConfigRec.FileMask;
- if Application^.ExecuteDialog(D, @ConfigRec) = cmOK then
- begin
- Uppercase(ConfigRec.FileMask);
-
- if ConfigRec.ShowHidden > 0 then
- UnwantedFiles := VolumeID or Directory
- else
- UnwantedFiles := VolumeID or Directory or SysFile or Hidden;
-
- if ConfigRec.FileMask <> SaveMask then
- Message(Desktop, evBroadcast, cmRescan, nil)
- else
- Message(Desktop, evBroadcast, cmRefreshDisplay, nil);
- end;
- end;
-
- procedure SaveConfig;
- var
- Result: Longint;
- F: PDosStream;
- Pal: PString;
- begin
- F := New(PDosStream, Init(GetExeBaseName + CFGExt, stCreate));
- Result := F^.Status;
- if Result <> 0 then
- begin
- MessageBox(RezStrings^.Get(sWriteCfgErr), @Result, mfError+mfOKButton);
- Exit;
- end;
- F^.Write(ConfigHeader[1], SizeOf(TConfigHeader) - 1);
- F^.Write(ConfigRec, SizeOf(TConfigRec));
- F^.Write(Viewer, SizeOf(FNameStr));
- Pal := @Application^.GetPalette^;
- F^.WriteStr(Pal);
- WriteAssociationList(F^);
- Dispose(F, Done);
- end;
-
- procedure ReadConfig;
- var
- Result: Longint;
- F: PDosStream;
- Header: TConfigHeader;
- Pal: PString;
- begin
- F := New(PDosStream, Init(GetExeBaseName + CFGExt, stOpenRead));
- Result := F^.Status;
- if Result <> 0 then Exit;
- F^.Read(Header[1], SizeOf(TConfigHeader) - 1);
- Header[0] := Char( SizeOf(TConfigHeader) -1 );
- if Header <> ConfigHeader then
- begin
- MessageBox(RezStrings^.Get(sInvalidCfgErr), nil, mfError + mfOKButton);
- Exit;
- end;
- F^.Read(ConfigRec, SizeOf(TConfigRec));
- F^.Read(Viewer, SizeOf(FNameStr));
- Pal := F^.ReadStr;
- if Pal <> nil then
- begin
- Application^.GetPalette^ := Pal^;
- DoneMemory;
- Application^.ReDraw;
- DisposeStr(Pal);
- end;
- ReadAssociationList(F^);
- Dispose(F, Done);
- end;
-
- procedure RunDosCommand(Command: String);
- var
- D: PDialog;
- Event: TEvent;
- begin
- D := PDialog( RezFile.Get('RunDialog') );
- if (Application^.ExecuteDialog(D, @Command) = cmOK) and
- (FullTrim(Command) <> '') then
- begin
- DoneSysError;
- DoneEvents;
- DoneVideo;
- DoneDosMem;
-
- SwapVectors;
- Exec(GetEnv('COMSPEC'), '/C' + Command);
- SwapVectors;
-
- PrintStr(RezStrings^.Get(sPressAnyKey));
- repeat
- GetKeyEvent(Event);
- until Event.What <> evNothing;
-
- InitDosMem;
- InitVideo;
- InitEvents;
- InitSysError;
-
- Application^.Redraw;
- end;
- end;
-
- function NewFileNameRec(const Path: FNameStr): PFileNameRec;
- var
- D: DirStr;
- N: NameStr;
- E: ExtStr;
- P: PFileNameRec;
- begin
- FSplit(Path, D, N, E);
- New(P);
- P^.Dir := D;
- P^.Name := N;
- P^.Ext := E;
- NewFileNameRec := P;
- end;
-
- procedure DragDropCopy(Mover: PFileMover; Dest: PathStr);
- var
- C: TCopier;
- TotalSize: Longint;
-
- procedure AddSizes(F: PFileRec); far;
- begin
- Inc(TotalSize, F^.Size);
- end;
-
- procedure CopyFiles(F: PFileRec); far;
- begin
- C.CopyFile(Mover^.Dir + '\' + F^.Name + F^.Ext,
- Dest + '\' + F^.Name + F^.Ext, coNormal);
- end;
-
- begin
- if Mover^.Dir = Dest then
- begin
- MessageBox('Files cannot be copied to same directory.',nil,
- mfError + mfOKButton);
- Exit;
- end;
-
- if MessageBox('Copy files to ' + Dest, nil, mfConfirmation +
- mfOKCancel) <> cmOK then Exit;
-
- C.Init(20);
- TotalSize := 0;
- Mover^.Items^.ForEach(@AddSizes);
-
- ShowCopyStatusBox(TotalSize);
- Mover^.Items^.ForEach(@CopyFiles);
-
- C.Done;
- KillStatusBox;
-
- InvalidateDir(Dest);
- end;
-
- function WildCardMatch(const Name, Card: FNameStr): Boolean;
- var
- I, J: Integer;
- begin
- WildCardMatch := False;
- J := 1;
- I := 1;
- while J <= Length(Card) do
- case Card[J] of
- '*':
- begin
- while (J <= Length(Card)) and (Card[J] <> '.') do Inc(J);
- while (I <= Length(Name)) and (Name[I] <> '.') do Inc(I);
- end;
- '?':
- begin
- Inc(J);
- Inc(I);
- end;
- '.':
- begin
- if I <= Length(Name) then
- if Name[I] <> '.' then
- Exit
- else
- Inc(I);
- Inc(J);
- end;
- else
- if (I > Length(Name)) or (Card[J] <> Name[I]) then Exit;
- Inc(I);
- Inc(J);
- end;
- WildCardMatch := (I > Length(Name)) and (J > Length(Card));
- end;
-
- { TStatusBox }
- procedure TStatusBox.HandleEvent(var Event:TEvent);
- begin
- inherited HandleEvent(Event);
- if (Event.What=evBroadcast) and (Event.Command = cmStatusUpdate) then
- DrawView;
- end;
-
-
- { TCopier }
- procedure TCopier.ReadMsg(const FName: FNameStr; Progress: Longint);
- begin
- StatusMsg := RezStrings^.Get(sReading) + FName;
- Message(StatusBox, evBroadcast, cmStatusUpdate, nil);
- Message(StatusBox, evBroadcast, cmAddGauge, Pointer(Progress div 2));
- end;
-
- procedure TCopier.WriteMsg(const FName: FNameStr; Progress: Longint);
- begin
- StatusMsg := RezStrings^.Get(sWriting) + FName;
- Message(StatusBox, evBroadcast, cmStatusUpdate, nil);
- Message(StatusBox, evBroadcast, cmAddGauge, Pointer(Progress div 2));
- end;
-
- function TCopier.IOError(const FName: FNameStr; ECode: Integer) : erAction;
- var
- Msg: String;
- D: PDialog;
- R: TRect;
- P: PView;
- begin
- Msg := ErrorMsg(ECode);
-
- R.Assign(0,0,55,7);
- D := New(PDialog, Init(R, FName));
- with D^ do
- begin
- Options := Options or ofCentered;
- R.Assign(2,2,52,3);
- Insert(New(PStaticText, Init(R, Msg)));
- R.Assign(20,4,32,6);
- Insert(New(PButton, Init(R, '~R~etry', cmOK, bfDefault)));
- R.Move(14,0);
- Insert(New(PButton, Init(R, '~A~bort', cmCancel, bfNormal)));
- SelectNext(False);
- end;
- if Application^.ExecuteDialog(D, nil) = cmOK then IOError := erRetry
- else IOError := erAbort;
- end;
-
- { TOkListBox }
-
- procedure TOkListBox.SelectItem(Item: Integer);
- var
- E: TEvent;
- begin
- inherited SelectItem(Item);
- with E do
- begin
- What := evCommand;
- Command := cmOk;
- InfoPtr := nil;
- end;
- PutEvent(E);
- end;
-
- end.
-